package com.quad.innovators.salesease.service.impl.warehouse;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.quad.innovators.salesease.common.result.PageResultBean;
import com.quad.innovators.salesease.common.utils.SystemCodeUtils;
import com.quad.innovators.salesease.converter.ArrivalOrderConverter;
import com.quad.innovators.salesease.enums.ArrivalScanStatusEnum;
import com.quad.innovators.salesease.enums.ResultCode;
import com.quad.innovators.salesease.enums.SystemCodeEnum;
import com.quad.innovators.salesease.exception.BusinessException;
import com.quad.innovators.salesease.mapper.warehouse.ArrivalOrderMapper;
import com.quad.innovators.salesease.mapper.warehouse.PurchaseOrderMapper;
import com.quad.innovators.salesease.model.dto.ProductArrivalDetailNumber;
import com.quad.innovators.salesease.model.entity.stock.ProductInfoIdentity;
import com.quad.innovators.salesease.model.entity.warehouse.ArrivalOrder;
import com.quad.innovators.salesease.model.entity.warehouse.PurchaseOrder;
import com.quad.innovators.salesease.model.entity.warehouse.SaleReturnOrder;
import com.quad.innovators.salesease.model.form.warehouse.ArrivalOrderDetailForm;
import com.quad.innovators.salesease.model.form.warehouse.ArrivalOrderForm;
import com.quad.innovators.salesease.model.form.warehouse.PurchaseOrderForm;
import com.quad.innovators.salesease.model.query.warehouse.ArrivalOrderPageQuery;
import com.quad.innovators.salesease.model.query.warehouse.PurchaseOrderPageQuery;
import com.quad.innovators.salesease.model.vo.warehouse.ArrivalOrderVO;
import com.quad.innovators.salesease.model.vo.warehouse.PurchaseOrderVO;
import com.quad.innovators.salesease.service.stock.ProductInfoIdentityService;
import com.quad.innovators.salesease.service.warehouse.ArrivalOrderDetailService;
import com.quad.innovators.salesease.service.warehouse.ArrivalOrderService;
import com.quad.innovators.salesease.service.warehouse.PurchaseOrderDetailService;
import com.quad.innovators.salesease.service.warehouse.PurchaseOrderService;

import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import lombok.RequiredArgsConstructor;

/**
 * @author : shanshan.li
 * @createTime : 2024/10/18 15:25
 * @Version : 1.0 
 */
@Service
@RequiredArgsConstructor
public class ArrivalOrderServiceImpl extends ServiceImpl<ArrivalOrderMapper, ArrivalOrder> implements ArrivalOrderService {

    private final ArrivalOrderConverter arrivalOrderConverter;
    private final ArrivalOrderDetailService arrivalOrderDetailService;
    private final ProductInfoIdentityService productInfoIdentityService;

    @Override
    public PageResultBean<ArrivalOrderVO> listPage(ArrivalOrderPageQuery queryParams) {
        Page<ArrivalOrderVO> page = new Page<>(queryParams.getPageNum(), queryParams.getPageSize());
        Page<ArrivalOrderVO> arrivalOrderVOPage = this.baseMapper.listPage(page, queryParams);
        return arrivalOrderConverter.toPageVo(arrivalOrderVOPage);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(ArrivalOrderForm form) {
        if (CollectionUtils.isEmpty(form.getArrivalOrderDetailFormList())) {
            throw BusinessException.resultCode(ResultCode.COLLECTION_NOT_EMPTY);
        }
        ArrivalOrder entity = arrivalOrderConverter.toEntity(form);
        LocalDate currentTime = LocalDate.now();
        String formatCurrent = currentTime.format(DateTimeFormatter.ofPattern("yyyyMMdd"));

        ArrivalOrder arrivalOrder = this.getOne(new QueryWrapper<ArrivalOrder>()
                .lambda()
                .likeRight(ArrivalOrder::getOrderNumber, formatCurrent)
                .orderByDesc(ArrivalOrder::getOrderNumber)
                .last("limit 1"));
        if (ObjectUtils.isEmpty(arrivalOrder)) {
            entity.setOrderNumber(formatCurrent + "00001");
        } else {
            entity.setOrderNumber(String.valueOf(Long.parseLong(arrivalOrder.getOrderNumber()) + 1));
        }
        entity.setCode(SystemCodeUtils.getCode(SystemCodeEnum.ARRIVAL_ORDER));
        return this.baseMapper.insert(entity) > 0
                && arrivalOrderDetailService.saveList(entity.getCode(), form.getArrivalOrderDetailFormList());
    }

    @Override
    public ArrivalOrderForm getFormData(String code) {
        ArrivalOrder arrivalOrder = this.baseMapper.selectOne(new QueryWrapper<ArrivalOrder>().lambda().eq(ArrivalOrder::getCode, code));
        if (ObjectUtils.isEmpty(arrivalOrder)) {
            throw BusinessException.resultCode(ResultCode.NOT_FOUND);
        }
        ArrivalOrderForm arrivalOrderForm = arrivalOrderConverter.toForm(arrivalOrder);
        arrivalOrderForm.setArrivalOrderDetailFormList(arrivalOrderDetailService.getListByArrivalOrderCode(code));
        return arrivalOrderForm;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(String code, ArrivalOrderForm form) {
        if (CollectionUtils.isEmpty(form.getArrivalOrderDetailFormList())) {
            throw BusinessException.resultCode(ResultCode.COLLECTION_NOT_EMPTY);
        }
        ArrivalOrder arrivalOrder = this.baseMapper.selectOne(new QueryWrapper<ArrivalOrder>().lambda().eq(ArrivalOrder::getCode, code));
        if (ObjectUtils.isEmpty(arrivalOrder)) {
            throw BusinessException.resultCode(ResultCode.NOT_FOUND);
        }
        ArrivalOrder entity = arrivalOrderConverter.toEntity(form);
        entity.setId(arrivalOrder.getId());
        return this.baseMapper.updateById(entity) > 0
                && arrivalOrderDetailService.updateList(code, form.getArrivalOrderDetailFormList());
    }

    @Override
    public boolean arrivalScan(String code, Integer scanStatus) {
        ArrivalOrder arrivalOrder = this.baseMapper.selectOne(new QueryWrapper<ArrivalOrder>().lambda().eq(ArrivalOrder::getCode, code));
        if (ObjectUtils.isEmpty(arrivalOrder)) {
            throw BusinessException.resultCode(ResultCode.NOT_FOUND);
        }
        arrivalOrder.setWarehouseScanStatus(scanStatus);
        return this.baseMapper.updateById(arrivalOrder) > 0;
    }

    @Override
    public ArrivalOrderForm getFormDataH5(String code) {
        ArrivalOrder arrivalOrder = this.baseMapper.selectOne(new QueryWrapper<ArrivalOrder>().lambda().eq(ArrivalOrder::getCode, code));
        if (ObjectUtils.isEmpty(arrivalOrder)) {
            throw BusinessException.resultCode(ResultCode.NOT_FOUND);
        }
        ArrivalOrderForm arrivalOrderForm = arrivalOrderConverter.toForm(arrivalOrder);
        List<ArrivalOrderDetailForm> listByArrivalOrderCode = arrivalOrderDetailService.getListByArrivalOrderCode(code);
        Set<String> arrivalOrderDetailCodeList = listByArrivalOrderCode.stream().map(ArrivalOrderDetailForm::getCode).collect(Collectors.toSet());
        List<ProductInfoIdentity> productInfoIdentityList = productInfoIdentityService.list(new QueryWrapper<ProductInfoIdentity>().lambda().in(ProductInfoIdentity::getArrivalOrderDetailCode, arrivalOrderDetailCodeList));
        Map<String, Map<String, ProductInfoIdentity>> stringMapMap = productInfoIdentityList.stream().collect(Collectors.groupingBy(ProductInfoIdentity::getArrivalOrderDetailCode, Collectors.toMap(ProductInfoIdentity::getPackingCode, model -> model)));
        listByArrivalOrderCode.forEach(model -> {
            model.setAlreadyScannedNumber(stringMapMap.getOrDefault(model.getCode(), new HashMap<>()).size());
        });
        arrivalOrderForm.setArrivalOrderDetailFormList(listByArrivalOrderCode);
        return arrivalOrderForm;
    }
}
